package com.demo.cms.filter;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.tuckey.web.filters.urlrewrite.extend.RewriteMatch;
import org.tuckey.web.filters.urlrewrite.extend.RewriteRule;
import org.tuckey.web.filters.urlrewrite.utils.Log;

import com.demo.common.StringUtils;
import com.demo.webapp.config.Constants;

/**
 * 站点的资源重写规则(忽略规则)
 * <br />根据站点Site资源字段resPath对请求的CMS站点资源(js、css、image等资源)进行过滤
 * 
 * @author ryuu.kk
 */
public class ResourcesRewriteRule extends RewriteRule {
	
	private static Log log = Log.getLog(ResourcesRewriteRule.class);

	/**
	 * 网站基础数据Map
	 * 该Map数据主要来源于info.properties配置文件
	 */
	private Map<String, Object> config;
	
	/**
	 * 所有站点的公共资源路径
	 */
	private static String[] resources = null;
	
	private ServletContext servletContext;
	
	 /**
	  * 规则初始化函数
	  * 如果返回false,则表示规则不可用
	  */
    @SuppressWarnings("unchecked")
	public boolean initialise(ServletContext servletContext) {
 		config = (Map<String, Object>) servletContext.getAttribute(Constants.CONFIG);
        //不存在配置,返回空Map
        if (config == null) {
        	config = new HashMap<String, Object>();
        }
        this.servletContext = servletContext;
        return true;
    }

    /**
     * 规则匹配方法matches调用后被执行。
     * 用于析构
     */
    public void destroy() {
        // by default do nothing
    }

    /**
     * 当前请求的匹配对象,如果不匹配则返回null
     *
     * @param request HttpServletRequest
     * @param response HttpServletResponse
     */
    public RewriteMatch matches(HttpServletRequest request, HttpServletResponse response) {
    	
    	String requestUri = request.getServletPath();
    	// 由于url重写在所有访问之前, 也就是在得到站点信息之前,所以这里需要过滤所有站点的公共资源
		// Site site = MultisiteContextHolder.getSite();
    	String[] resourcePaths = getResourcePaths(request);
    	boolean isMatch = false;
    	for (String resPath : resourcePaths) {
    		isMatch = requestUri.startsWith(resPath);
    		if (isMatch) {
    			break;
    		}
    	}
		if (isMatch) {
			if (log.isDebugEnabled()) {
				log.debug("Url Rewrite Rule [Ignore CMS_Resource ：" + requestUri + "]");
			}
			/* ***********************************************************
			 * 使用请求转发造成不必要的资源浪费,则清除掉请求转发形式   2013-06-28
			 * 
			 ************************************************************* */
			return new RewriteMatch(){
				boolean requestRewritten = false; 
	        	private String matchingUrl = "";
				public String getMatchingUrl() {
					return this.matchingUrl;
				}
				public boolean execute(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
					String target = request.getServletPath();
					if (response.isCommitted()) {
			            log.error("response is comitted cannot forward to " + target +
			                    " (check you haven't done anything to the response (ie, written to it) before here)");
			        } else {
			      		RequestDispatcher rq;
						try {
							rq = getRequestDispatcher(request, target, servletContext);
							rq.forward(request, response);
						} catch (ServletException e) {
							e.printStackTrace();
						} catch (IOException e) {
							e.printStackTrace();
						}
			            if (log.isTraceEnabled()) log.trace("forwarded to " + target);
			        }
			        requestRewritten = true;
			        
			        return requestRewritten;
				}
			};
//			return new RewriteMatch() {
//	        	private String matchingUrl = ;
//				public String getMatchingUrl() {
//					return this.matchingUrl;
//				}
//			};
		}
		return null;
    }
    
    /**
     * 获得所有资源路径
     * @param request HttpServletRequest 
     * @return String[] 所有站点的资源路径列表
     */
    @SuppressWarnings("unchecked")
	private String[] getResourcePaths(HttpServletRequest request) {
    	if (resources == null) {
    		if (config == null) {
    			config = (Map<String, Object>) request.getSession().getServletContext().getAttribute(Constants.CONFIG);
    		}
        	if (config == null) {
        		return new String[]{};
        	}
        	
        	List<String> resourcePaths = new ArrayList<String>(); 
        	Set<String> keySet = config.keySet();
        	for (String key : keySet) {
        		Object obj = config.get(key);
        		if (obj instanceof Map) {
        			// 得到站点配置MAP
        			Map<String, Object> siteConfig = (Map<String, Object>) obj;
    				String resPath = (String) siteConfig.get(com.demo.webapp.config.Constants.PUBLISH_FOLDER_KEY);
    				if (StringUtils.isNotEmpty(resPath)) {
    					resourcePaths.add(getResPath(resPath));
    				}
        		}
        	}
        	resources = resourcePaths.toArray(new String[]{});
    	}
    	return resources;
    }
    
	/**
	 * 取得站点资源路径
	 * @param site Site
	 * @return String
	 */
	protected String getResPath(String resPath) {
		if (StringUtils.isNotEmpty(resPath)) {
			if (resPath.charAt(0) != '/' ) {
				resPath = "/" + resPath;
			}
			if (resPath.charAt(resPath.length() - 1) != '/') {
				resPath += "/";
			}
		}
		return resPath;
	}
	
	private RequestDispatcher getRequestDispatcher(final HttpServletRequest hsRequest, String toUrl, ServletContext targetContext) throws ServletException {
		String target = toUrl;
		final RequestDispatcher rq = (targetContext != null) ? targetContext
				.getRequestDispatcher(target) : hsRequest
				.getRequestDispatcher(toUrl);
		if (rq == null) {
			// this might be a 404 possibly something else, could re-throw a 404
			// but is best to throw servlet exception
			throw new ServletException("unable to get request dispatcher for " + toUrl);
		}
		return rq;
	}

}
